package com.pocket.insight.base.sql.rewriter;

import com.google.common.collect.Sets;
import com.pocket.insight.base.cache.CacheStorage;
import com.pocket.insight.base.cache.ThreadCacheStorage;
import com.pocket.insight.base.context.MethodConst;
import com.pocket.insight.base.exception.BizException;
import com.pocket.insight.base.sql.Dialect;
import com.pocket.insight.base.sql.Rewriter;
import com.pocket.insight.base.utils.ParamAttrUtil;
import com.pocket.insight.base.utils.SerializationUtils;
import com.pocket.insight.entity.AppParam;
import com.pocket.insight.entity.ME;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 描述：
 *
 * @author shuize
 * @create 2024/12/10
 */
public class ParamAttrRewriter implements Rewriter {

    public static <T> T rewriteClassWithSymbolCheck(T t, Dialect dialect, AppParam.ValueMap appParamValueMap) {
        return t == null ? null : (T) SerializationUtils.toJavaObject((new ParamAttrRewriter()).rewriteWithSymbolCheck(SerializationUtils.toJSONString(t), dialect, appParamValueMap), t.getClass());
    }

    public String rewriteWithSymbolCheck(String meStr, Dialect dialect, AppParam.ValueMap appParamValueMap) {
        return this.rewrite(meStr, dialect, Sets.newHashSet(new ME.Kind[]{ME.Kind.attr, ME.Kind.param}), true, appParamValueMap);
    }

    public String rewrite(String meStr, Dialect dialect, Set<ME.Kind> kinds, boolean forbidHiddenAttrs, AppParam.ValueMap appParamValueMap) {
        ME.Kind kind;
        for (Iterator kindsIterator = CollectionUtils.emptyIfNull(kinds).iterator(); kindsIterator.hasNext(); meStr = this.rewriteParamAttrImpl(meStr, dialect, kind, forbidHiddenAttrs, appParamValueMap)) {
            kind = (ME.Kind) kindsIterator.next();
        }
        return meStr;
    }

    private String rewriteParamAttrImpl(String meStr, Dialect dialect, ME.Kind kind, boolean forbidHiddenAttrs, AppParam.ValueMap appParamValueMap) {
        Pattern pattern = Pattern.compile(kind == ME.Kind.param ? "\\{\\{%%.+?\\}\\}" : (kind == ME.Kind.apiparam ? "\\{\\{##.+?\\}\\}" : "\\{\\{\\$\\$.+?\\}\\}"));
        Matcher matcher = pattern.matcher(meStr);
        Set<String> usedParameters = new HashSet();
        while(matcher.find()) {
            String parameter = matcher.group();
            usedParameters.add(parameter);
        }

        Set<String> hiddenAttrs = (Set) CacheStorage.get(ThreadCacheStorage.ThreadCacheKeysEnum.HIDDEN_USER_ATTRS);
        if (hiddenAttrs == null) {
            hiddenAttrs = new HashSet();
        }

        if (!usedParameters.isEmpty()) {
            Iterator var10 = usedParameters.iterator();
            while(true) {
                while(true) {
                    String p;
                    String attr;
                    Object value;
                    Object argObj;
                    while(true) {
                        if (!var10.hasNext()) {
                            return meStr;
                        }
                        p = (String)var10.next();
                        attr = p.substring(4, p.length() - 2);
                        value = null;
                        argObj = null;
                        if (kind == ME.Kind.param) {
                            if (appParamValueMap == null) {
                                continue;
                            }
                            argObj = getAppParameter(appParamValueMap, attr);
                            AppParam.Options paramOptions = null;
                            try {
                                paramOptions = (AppParam.Options)argObj;
                            } catch (Exception var17) {
                                value = argObj;
                            }
                            if (paramOptions != null) {
                                value = paramOptions.getCurrentValue() != null ? paramOptions.getCurrentValue() : this.getParamCurrentValueByOptions(appParamValueMap, attr, paramOptions);
                                if (paramOptions.getMultiValueConfig() != null && BooleanUtils.isTrue(paramOptions.getMultiValueConfig().getEnable())) {
                                    value = ParamAttrUtil.buildParamMultiValue(value, paramOptions.getMultiValueConfig());
                                }
                            }
                            break;
                        }
                        if (kind == ME.Kind.apiparam) {
                            //value = getApiParameter(attr);
                            break;
                        }
                        if (forbidHiddenAttrs && ((Set)hiddenAttrs).contains(attr)) {
                            break;
                        }
                        break;
                    }

                    String dialectValue;
                    if (value == null) {
                        if (kind == ME.Kind.param) {
                            if (argObj == null) {
                                throw new BizException("ERROR_APP_PARAM_NOT_EXISTS: " + attr);
                            }
                        } else {
                            if (kind != ME.Kind.attr) {
                                if (kind == ME.Kind.apiparam) {
                                    throw new BizException("ERROR_CUSTOM_API_CONFIG_ERROR");
                                }
                                continue;
                            }
                            if (argObj == null) {
                                throw new BizException("ERROR_USER_ATTR_NOT_EXISTS_OR_EMPTY：" + attr);
                            }
                        }
                        value = dialect == null ? "null" : dialect.nullVal();
                    } else if (value instanceof List) {
                        List<Object> args = (List)((List)value).stream().map(v -> v instanceof String ? String.format("'%s'", v) : v
                        ).collect(Collectors.toList());
                        value = String.format("(%s)", StringUtils.join(args, ","));
                    } else {
                        value = value.toString();
                    }
                    meStr = meStr.replace(p, (CharSequence) value);
                }
            }
        } else {
            return meStr;
        }
    }

    public static Object getAppParameter(AppParam.ValueMap appParamValueMap, String key) {
        Object paramValue = appParamValueMap.getSpecificAppParamValue(key);
        if (paramValue instanceof BizException bizException) {
            throw bizException;
        } else {
            return paramValue;
        }
    }

    private Object getParamCurrentValueByOptions(AppParam.ValueMap appParamValueMap, String paramName, AppParam.Options options) {
        Pair<Method, Object> methodObjectPair = MethodConst.PRESET_METHOD_MAP.get("com.pocket.insight.service.AppService|setAppParamCurrentValueByOptions");
        if (methodObjectPair == null) {
            return null;
        } else {
            try {
                (methodObjectPair.getLeft()).invoke(methodObjectPair.getRight(), appParamValueMap.getAppId(), paramName, options);
            } catch (Exception var6) {
            }

            AppParam.Options paramOptions = (AppParam.Options)getAppParameter(appParamValueMap, paramName);
            return paramOptions.getCurrentValue();
        }
    }

}
